package com.mall.pay.services;

import com.mall.order.OrderCoreService;
import com.mall.order.dto.PayOrderSuccessRequest;
import com.mall.order.dto.PayOrderSuccessResponse;
import com.mall.pay.PayCoreService;
import com.mall.pay.constants.PayResultEnum;
import com.mall.pay.constants.PayReturnCodeEnum;
import com.mall.pay.dal.entitys.Payment;
import com.mall.pay.dal.persistence.PaymentMapper;
import com.mall.pay.dto.PaymentRequest;
import com.mall.pay.dto.PaymentRequest_X;
import com.mall.pay.dto.alipay.AlipayQueryRetResponse;
import com.mall.pay.dto.alipay.AlipaymentResponse;
import lombok.extern.slf4j.Slf4j;

import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;

/**
 * @author XuBang
 * @TODO:
 * @date 2021/11/4$
 * @trainOfthought:
 */
@Slf4j
@Component
@Service
//如果没有改行注解，会报如下异常：
/**
 * org.apache.dubbo.rpc.RpcException:
 * No provider available from registry 127.0.0.1:2181 for service
 * com.mall.pay.PayCoreService on consumer 192.168.7.12 use dubbo version 2.7.3,
 * please check status of providers(disabled, not registered or in blacklist).
 */
public class PayCoreServiceImpl_X implements PayCoreService {

    //注入PayHelper_X:使用其中的方法
    @Autowired
    PayHelper_X payHelper_x;

    //通用paymentMapper:对tb_payment进行操作
    @Autowired
    PaymentMapper paymentMapper;

//    @Autowired(required=false)    //表示忽略当前要注入的bean，如果有直接注入，没有跳过，不会报错。不是通过一个spring容器
    //所以，不能使用@Autowired；只能使用@Reference
    @Reference(check = false, retries = 0)
    OrderCoreService orderCoreService;


    /**
     * 任务一：获取支付二维码
     * @param request
     * @return
     */
    @Override
    public AlipaymentResponse aliPay(PaymentRequest request) {

        //0.定义response对象，用于封装结果，响应
        AlipaymentResponse response = new AlipaymentResponse();

        //1.调用PayHelper中的方法，实现支付二维码的获取
        String qrCodeName = payHelper_x.test_trade_precreate(request);  //传入request，所以：需要对PayHelper_X中的对应方法传参&返参，微调

        //2. 获取返回结果（失败状态的response封装）
        if (qrCodeName==null){
            response.setCode(PayReturnCodeEnum.GET_CODE_FALIED.getCode());
            response.setMsg(PayReturnCodeEnum.GET_CODE_FALIED.getMsg());
            return response;
        }

        //2. 获取返回结果（成功状态的response封装）---------
        // --------获取二维码图片成功：在tb_payment中针对待支付的订单生成一条记录，记录该订单的支付信息 status PAY_PROCESSING

        //a.采用tk_mybatis，准备响应的工具，对tb_payment进行操作
        //b.在tb_payment中针对待支付的订单生成一条记录，记录该订单的支付信息 status PAY_PROCESSING
        Payment payment = new Payment();
//        payment.setId(request.ge);  //先默认看看
        payment.setOrderId(request.getTradeNo());  //需要根据userId，去tb_order，查询批量的orderId;
        payment.setCompleteTime(new Date());
        payment.setCreateTime(new Date());
        payment.setPayerName("徐小棒");  //根据userId,从tb_user_verify中查询username;暂时不查，假定一个
        payment.setOrderAmount(request.getOrderFee());
        payment.setPayerAmount(request.getTotalFee());
        payment.setPayerUid(request.getUserId());
//        payment.setPayNo(request.getTradeNo());  //交易订单号
//        payment.setPaySuccessTime(); //支付成功时间
        payment.setPayWay(request.getPayChannel());
        payment.setProductName(request.getSubject());
        payment.setRemark(request.getPayChannel());  //扩展字段
        payment.setStatus(String.valueOf(PayResultEnum.PAY_PROCESSING));
        payment.setUpdateTime(new Date());

        paymentMapper.insert(payment);

        response.setCode(PayReturnCodeEnum.SUCCESS.getCode());
        response.setMsg(PayReturnCodeEnum.SUCCESS.getMsg());
        response.setQrCode(qrCodeName);
        return response;
    }

    /**
     * 查询支付结果
     * @param request
     * @return
     */
    @Override
    public AlipayQueryRetResponse queryAlipayRet(PaymentRequest_X request) {   //获取订单it -tradeNo

           //0.定义response对象，用于封装结果，响应
        AlipayQueryRetResponse response = new AlipayQueryRetResponse();

        Payment payment = new Payment();

        //1.调用PayHelper中的方法，查询支付结果
        boolean payResult = payHelper_x.test_trade_query(request);   //payResult true；表示支付成功
        if (payResult) {   //支付成功
            //1. 修改tb_payment表中针对，指定订单的支付结果，支付成功时间，支付完成时间等 status PAY_SUCCESS
             //a.制定规则：根据交易订单号进行修改（交易订单号唯一）****************这样的想法，有待测试结果验证************
            Example example = new Example(Payment.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("orderId",request.getTradeNo());   //***********

             //b.制定修改对象

            payment.setUpdateTime(new Date());  //订单修改时间
            payment.setPaySuccessTime(new Date());  //订单支付时间
            payment.setStatus(String.valueOf(PayResultEnum.PAY_SUCCESS));  //订单支付状态

            paymentMapper.updateByExampleSelective(payment,example);

            //  orderCoreService.payOrderSuccess():下方逻辑，都放在payOrderSuccess中进行处理；此处仅仅调用；涉及不同的进程，pay服务没有权限，
            //  跨进程调用order服务对应的数据库；只能DI注入，order服务暴露给外部的已经实现的接口来执行

            //2. 修改订单相应的数据: 修改订单的状态为已支付
            //3. 遍历订单中的订单商品条目，根据订单商品条目中商品购买的数量，去扣减对应商品的锁定库存
            //4. 返回查询结果的响应  SUCCESS
            PayOrderSuccessRequest payOrderSuccessRequest = new PayOrderSuccessRequest();
            payOrderSuccessRequest.setOrderId(request.getTradeNo());  //*************************************尚哥说orderId==tradeNo,true   需要进一步验证---->验证，正确；从controller层证明
            orderCoreService.payOrderSuccess(payOrderSuccessRequest);  //修改方法，不存在返回值
            //注:成功状态


            response.setCode(PayReturnCodeEnum.SUCCESS.getCode());
            response.setMsg(PayReturnCodeEnum.SUCCESS.getMsg());
            response.setResult("哈哈");
            return response;
        } else {  //支付失败
            // 1. 修改tb_payment表中针对，指定订单的支付结果，支付完成时间等 status PAY_FAILPayReturnCodeEnum
             //a.指定修改规则
            Example example = new Example(Payment.class);
            Example.Criteria criteria = example.createCriteria();
            criteria.andEqualTo("orderId",request.getTradeNo());  //根据订单id orderId

            payment.setUpdateTime(new Date());  //订单修改时间
            payment.setPaySuccessTime(new Date());  //订单支付时间
            payment.setStatus(String.valueOf(PayResultEnum.PAY_FAIL));  //订单支付状态-失败
            //b.修改
            paymentMapper.updateByExampleSelective(payment,example);

            // 2. 返回查询结果的响应 ORDER_HAD_NOT_PAY
            response.setCode(PayReturnCodeEnum.PAYMENT_PROCESSOR_FAILED.getCode());
            response.setMsg(PayReturnCodeEnum.PAYMENT_PROCESSOR_FAILED.getMsg());
            response.setResult(null);
            return response;
        }
    }
}
